# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
# This source file is part of the Cangjie project, licensed under Apache-2.0
# with Runtime Library Exception.
#
# See https://cangjie-lang.cn/pages/LICENSE for license information.


from os import path
import random

integer_types = ['Int8', 'Int16', 'Int32', 'Int64', 'IntNative', 'UInt8', 'UInt16', 'UInt32', 'UInt64', 'UIntNative']
other_types = ['Float16', 'Float32', 'Float64', 'String', 'Rune', 'Bool', 'Unit', '(Int8, Int8)', 'Array<Int8>', 'C']
types = integer_types + other_types
default_value_map = {'Bool' : 'true', 'Unit' : '()', 'Array<Int8>' : '[1]', 'Rune' : "'1'", 'String' : '"1"', '(Int8, Int8)' : '(1, 1)', 'C' : 'C()'}
def default_value(ty : str) -> str:
  if ty in integer_types: return '1'
  if 'Float' in ty: return '1.0'
  return default_value_map[ty]
dir = path.dirname(path.realpath(__file__))
path = dir + '/test_' + path.basename(dir) + '_{}.cj'
negative_template = '''
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

/*
  @Assertion:   4.22.1(2) Here, e2 is the expression of the function type. The type of e1 matches the parameter type of
                e2. Or the type of e2 implements the operator () overloading, (see Operators that can be Overloaded),
                i.e. e1 |> e2 is the syntactic sugar of let v = e1; e2(v) and e2(v) is the function call overloading.
                See section 4.13.2 for details.
  @Description: Checks that using operator |> with types {t1} and {t2} is not permitted.
  @Mode: compileonly
  @Negative: yes
  @Structure: single
  @CompileWarning: no
  @Comment: Auto-generated by gen.py
*/
{}
main() {{
    var v1 : {t1} = {}
    var v2 : {t2} = {}
    let v3 = v1 |> v2
}}
'''
positive_template = '''
/*
 * Copyright (c). 2023-2023. All rights reserved.
 */

/*
  @Assertion:   4.22.1(2) Here, e2 is the expression of the function type. The type of e1 matches the parameter type of
                e2. Or the type of e2 implements the operator () overloading, (see Operators that can be Overloaded),
                i.e. e1 |> e2 is the syntactic sugar of let v = e1; e2(v) and e2(v) is the function call overloading.
                See section 4.13.2 for details.
  @Description: Checks that using operator |> with types T1 and (T1) -> T2 is permitted for various T1 and T2.
  @Mode: run
  @Negative: no
  @Structure: single
  @CompileWarning: ignore
  @Comment: Auto-generated by gen.py
*/

class C {}

%s

main() {
%s
    return 0
}
'''
class_decl = '\nclass C ()\n'
counter = 2
limit = 100
random.seed(123)

def write_counted(contents : str):
  global counter
  with open(path.format(str(counter).zfill(3)), 'w') as file:
    file.write(contents)
    counter += 1

def mangle(t : str):
  if t == '(Int8, Int8)': return 'Tuple'
  if 'Array' in t: return 'Array'
  return t

write_counted(positive_template % (
'\n\n'.join( ['func f%s%s(x : %s) : %s { %s }' % (mangle(t1), mangle(t2), t1, t2, default_value(t2)) for t1 in types for t2 in types]),
'\n'.join(['    %s |> f%s%s' % (default_value(t1), mangle(t1), mangle(t2)) for t1 in types for t2 in types])))
regular_types_tests = [negative_template.format(class_decl if 'C' in (t1, t2) else '', default_value(t1), default_value(t2),
                                                t1=t1, t2=t2) for t1 in types for t2 in types]
func_type_tests = [negative_template.format(class_decl if 'C' in (t1, t2) else '', default_value(t1),
'{ x : %s => %s }' % (t2, default_value(t3)), t1=t1, t2='(%s) -> %s' % (t2, t3))
                    for t1 in types for t2 in types if t1 != t2 for t3 in types]
for test in random.sample(regular_types_tests, limit) + random.sample(func_type_tests, limit):
  write_counted(test)
